﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Collections.ObjectModel;
using Wizard.WizardControl.Models;
using CoffeeLibrary;
using System.ComponentModel;
using Wizard.CoffeeView;
using Wizard.WizardControl.Helpers;
using Wizard.WizardControl;

namespace Wizard.CoffeeModel
{

    public class TypeSizeStepViewModel : WizardStepViewModelBase<CupOfCoffee>
    {

        RegularOptionGroupViewModel<BeanType> _availableBeanTypes;
        RouteOptionGroupViewModel<DrinkSize> _availableDrinkSizes;

        public TypeSizeStepViewModel( CupOfCoffee cupOfCoffee )
            : base( cupOfCoffee )
        {
        }

        /// <summary>
        /// Returns a read-only collection of all bean types that the user can select.
        /// </summary>
        public RegularOptionGroupViewModel<BeanType> AvailableBeanTypes
        {
            get
            {
                if ( _availableBeanTypes == null )
                {
                    this.CreateAvailableBeanTypes();
                }
                return _availableBeanTypes;
            }
        }

        void CreateAvailableBeanTypes()
        {
            List<OptionViewModel<BeanType>> list = new List<OptionViewModel<BeanType>>();
            list.Add( new OptionViewModel<BeanType>( BeanType.Organic, 1, "Sorry, organic just means more expensive" ) );
            list.Add( new OptionViewModel<BeanType>( BeanType.Breakfast, 2, "Don't drink after noon" ) );
            list.Add( new OptionViewModel<BeanType>( BeanType.DarkRoast, 3, "Rich flavor!" ) );
            list.Add( new OptionViewModel<BeanType>( BeanType.House, 4, "Cheap and nasty" ) );
            list.Add( new OptionViewModel<BeanType>( BeanType.LightRoast, 5, "This is, flavorless" ) );

            foreach ( OptionViewModel<BeanType> option in list )
            {
                // Select the default value.
                if ( option.GetValue() == base.BusinessObject.BeanType )
                {
                    option.IsSelected = true;
                }
                option.PropertyChanged += this.OnBeanTypeOptionPropertyChanged;
            }

            list.Sort();

            _availableBeanTypes = new RegularOptionGroupViewModel<BeanType> { OptionModels = new ReadOnlyCollection<OptionViewModel<BeanType>>(list) };
        }

        void OnBeanTypeOptionPropertyChanged( object sender, PropertyChangedEventArgs e )
        {
            OptionViewModel<BeanType> option = sender as OptionViewModel<BeanType>;
            if ( option.IsSelected )
            {
                this.BusinessObject.BeanType = option.GetValue();
            }
        }

        /// <summary>
        /// Returns a read-only collection of all drink sizes that the user can select.
        /// </summary>
        public RouteOptionGroupViewModel<DrinkSize> AvailableDrinkSizes
        {
            get
            {
                if ( _availableDrinkSizes == null )
                {
                    this.CreateAvailableDrinkSizes();
                }
                return _availableDrinkSizes;
            }
        }

        /// <summary>
        /// Here's where create a RouteOptionGroupViewModel that may alter the workflow of the wizard.
        /// </summary>
        void CreateAvailableDrinkSizes()
        {
            /// Each RouteOptionViewModel has a NextStepViewType property that will tell the WizardViewModel which step (by view type) will be next
            /// when that option is selected.
            var list = new List<RouteOptionViewModel<DrinkSize>>();
            list.Add( new RouteOptionViewModel<DrinkSize>( DrinkSize.Small, 0, "Teensy" ) );
            list.Add( new RouteOptionViewModel<DrinkSize>( DrinkSize.Medium, 1, "EXTRA Medium" ) );
            list.Add( new RouteOptionViewModel<DrinkSize>( DrinkSize.Large, 2, "Grande" ) );

            /// Respond to PropertyChanged so we can set the main business object's property
            list.ForEach( option => option.PropertyChanged += this.OnDrinkSizeOptionPropertyChanged );

            list.Sort();

            /// Put the RouteOptionViewModel objects into a RouteOptionGroupViewModel (see CoffeeTypeSizePageView, search "RouteOptionGroupView").
            var groupName = typeof( DrinkSize ).Name.SplitCamelCase();
            _availableDrinkSizes = new RouteOptionGroupViewModel<DrinkSize>( groupName ) { OptionModels = new ReadOnlyCollection<RouteOptionViewModel<DrinkSize>>( list ) };
        }

        public override RouteModifier OnNext()
        {
            /// If they've selected small, eliminate the extras step
            if ( GetSelectedDrinkSize().GetValue() == DrinkSize.Small )
            {
                return new RouteModifier { ExcludeViewTypes = new List<Type> { typeof( CoffeeExtrasPageView ) } };
            }
            /// If not we need to "include" the extras step: they may have gone next/back/next
            else
            {
                return new RouteModifier { IncludeViewTypes = new List<Type> { typeof( CoffeeExtrasPageView ) } };
            }
        }

        private RouteOptionViewModel<DrinkSize> GetSelectedDrinkSize()
        {
            return _availableDrinkSizes.OptionModels.FirstOrDefault( o => o.IsSelected );
        }

        void OnDrinkSizeOptionPropertyChanged( object sender, PropertyChangedEventArgs e )
        {
            OptionViewModel<DrinkSize> option = sender as OptionViewModel<DrinkSize>;
            if ( option.IsSelected )
            {
                this.BusinessObject.DrinkSize = option.GetValue();
            }
        }

        public override string DisplayName
        {
            get { return "Drink Size / Bean Type"; }
        }

        public override bool IsValid()
        {
            return GetSelectedDrinkSize() != null;
        }

    }

}
